#include "cmdmatrix.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "commmsg.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_MATRIX, CCmdMatrix);

int CCmdMatrix::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_MATRIX ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_MATRIX,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);

    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam); //消息解析
    if (iRet)
    {
        return AnsClients(iRet);
    }

	chSubCmd = stReq.sub_type();
    uiGID = stReq.gid();

    //检查登录
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    stAns.set_gid((int)uiGID);
    stAns.set_sub_type(chSubCmd);

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdMatrix::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, uiGID);

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
	{
        CT_ERROR(("no base data user(%u)", uiGID));
        return AnsClients(RET_SYSTEM_FAIL);
	}
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex]; 

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
	{
        CT_ERROR(("no detail data user(%u)", uiGID));
        return AnsClients(RET_SYSTEM_FAIL);
	}
	CPlayerDetailInfo& stPlayerDetail = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("no online data user %u", uiGID));
        return AnsClients(RET_SYSTEM_FAIL);
    }
	CPlayerOnlineData& stPlayerOnline = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //检查系统是否开启
    if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_1, stPlayerBaseInfo, stPlayerOnline))
    {
        return AnsClients(ERROR_SYS_NOT_OPEN);
    }
    
	switch (chSubCmd)
	{
	case CMatrixMgr::CMD_MATRIX_SUB_GET:
    case CMatrixMgr::CMD_MATRIX_SUB_FIGHTING:
        {
    	    iRet = pstMainCtrl->m_stMatrixMgr.GetMatrixData(stPlayerBaseInfo,
                stPlayerDetail, stPlayerOnline, stAns);
        }
		break;
	case CMatrixMgr::CMD_MATRIX_SUB_SET:
        {
    	    iRet = pstMainCtrl->m_stMatrixMgr.SetMainMatrix(stPlayerBaseInfo,
                stPlayerDetail, stPlayerOnline, stReq, stAns);
        }
		break;
	case CMatrixMgr::CMD_MATRIX_SUB_ADD:
        {
            iRet = pstMainCtrl->m_stMatrixMgr.AddToMatrix(stPlayerBaseInfo,
                stPlayerDetail, stPlayerOnline, stReq, stAns);
            
            if (RET_OK == iRet)
            {
                unsigned short shResID = 0;
                if (stReq.unit_datas_size() > 0)
                {
                    const MsgMatrixUnit& stMsgMatrixUnit = stReq.unit_datas(0);

                    if (stMsgMatrixUnit.type() == GAME_OBJ_TYPE_PARTNER)
                    {
                        shResID = stMsgMatrixUnit.id();
                    }
                }

                pstMainCtrl->m_stTaskMgr.TriggerDoSomeOpt(stPlayerOnline._stUserTask, 110000 + shResID, 1);
            }
        }
		break;
	case CMatrixMgr::CMD_MATRIX_SUB_DEL:
        {
    	    iRet = pstMainCtrl->m_stMatrixMgr.DelFromMatrix(stPlayerBaseInfo,
                stPlayerDetail, stPlayerOnline, stReq, stAns, true);
        }
		break;
	case CMatrixMgr::CMD_MATRIX_SUB_SWAP_OBJ:
        {
    	    iRet = pstMainCtrl->m_stMatrixMgr.SwapTwoMatrix(stPlayerBaseInfo,
                stPlayerDetail, stPlayerOnline, stReq, stAns);
        }
		break;
	case CMatrixMgr::CMD_MATRIX_SUB_SWAP_ORDER:
        {
    	    iRet = pstMainCtrl->m_stMatrixMgr.SwapTwoOrder(stPlayerBaseInfo,
                stPlayerDetail, stPlayerOnline, stReq, stAns);
        }
		break;
	default:
		iRet = ERROR_MATRIX_SUB_CMD;
		break;
	}

    if (iRet)
    {
        if (ERROR_MATRIX_REQINFO_NOT_MATCH == iRet ||
            ERROR_MATRIX_ORDER_INVALID == iRet ||
            ERROR_MATRIX_PARTNER_ALREADY == iRet)
        {
            pstMainCtrl->m_stMatrixMgr.NotifyMatrix(stPlayerBaseInfo,
                stPlayerDetail, stPlayerOnline);
        }
        CT_TRACE(("user(gid=%u) deal matrix op(sub=%d) error(%d)",uiGID,chSubCmd,iRet));
        return AnsClients(iRet);
    }

	if (chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_SET ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_ADD ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_DEL ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_SWAP_OBJ ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_SWAP_ORDER)
	{
    	//保存数据 detail info
    	CVarObjectKey stKey;
    	stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    	stKey.m_u64ID = uiGID;
    	pstMainCtrl->UpdateData(stKey, stPlayerDetail, VOP_UPDATE);
	}

    return AnsClients(RET_OK);
}

int CCmdMatrix::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        return Done(RET_SYS_ERROR);
    }

    //因为坐骑阵位属性这里再才触发重算以及下发
	if (chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_SET ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_ADD ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_DEL ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_SWAP_OBJ ||
		chSubCmd == CMatrixMgr::CMD_MATRIX_SUB_SWAP_ORDER)
	{
        pstMainCtrl->m_stNotifyMgr.Notify(uiGID,
            NOTIFY_ROLE_ATTR | NOTIFY_PARTNER_ATTR);
        pstMainCtrl->FlushSendCache();
	}

    return Done(iRet);
}

